<?php


namespace App\Service\College;

use App\Models\College\CollegeTrainingOrderModel;
use App\Models\College\CollegeTrainingOrderUserModel;
use App\Models\College\CollegeTrainingPlanModel;
use App\Service\BaseService;
use Exception;

class TrainingPlansService
{


    /**
     * 获取培训计划列表
     * @param $pageSize
     * @param $pageNum
     * @param $name
     * @param $campus
     * @param $planStartTime
     * @param $planEndTime
     * @param $status
     * @return mixed
     */
    public static function getTrainingPlansList($pageSize, $pageNum, $name, $campus, $planStartTime, $planEndTime, $status)
    {
        $paginator = CollegeTrainingPlanModel::query()
            ->when($name, function ($query) use ($name) {
                $query->where('name', 'like', "%{$name}%");
            })
            ->when($campus, function ($query) use ($campus) {
                $query->where('campus', $campus);
            })
            ->when($status != "", function ($query) use ($status) {
                $query->where('status', $status);
            })
            ->when($planStartTime, function ($query) use ($planStartTime) {
                $query->where('planStartTime', '>=', strtotime($planStartTime));
            })
            ->when($planEndTime, function ($query) use ($planEndTime) {
                $query->where('planStartTime', '<=', strtotime($planEndTime));
            })
            ->with(['orderRel' => function ($query) {
                $query->with('planUserRel', 'userRel');
            }])
            ->orderBy('planStartTime')
            ->paginate($pageSize, ['id', 'name', 'type', 'campus', 'planStartTime', 'planEndTime', 'createdAt', 'status'], 'page', $pageNum);

        $list = $paginator->map(
            function (CollegeTrainingPlanModel $collegeTrainingPlanModel) {
                $totalUser = $okUser = 0;

                $planNum = collect($collegeTrainingPlanModel->orderRel)
                    ->whereIn('status', [CollegeTrainingOrderModel::STATUS_MERCHANT_CONFIRM, CollegeTrainingOrderModel::STATUS_COLLEGE_CONFIRM, CollegeTrainingOrderModel::STATUS_ING, CollegeTrainingOrderModel::STATUS_WAIT_UPLOAD, CollegeTrainingOrderModel::STATUS_FINISH])
                    ->sum('planNum');//商家确认后 才是预计参训人数

                $actualNum = collect($collegeTrainingPlanModel->orderRel)
                    ->whereIn('status', [CollegeTrainingOrderModel::STATUS_ING, CollegeTrainingOrderModel::STATUS_WAIT_UPLOAD, CollegeTrainingOrderModel::STATUS_FINISH])
                    ->sum('actualNum');//商学院确认后 才是实际参训人数

                foreach ($collegeTrainingPlanModel->orderRel->where('status', '!=', CollegeTrainingOrderModel::STATUS_CLOSE)->toArray() as $v) {
                    if ($v['user_rel'] && $actualNum > 0) {
                        foreach ($v['user_rel'] as $vv) {
                            if ($vv['cruiseOrderId'] > 0) {
                                $totalUser++;//有试卷id 才是总考试人数
                                if ($vv['examResult'] == CollegeTrainingOrderUserModel::RESULT_OK) {
                                    $okUser++;//理论合格
                                }
                            }
                        }
                    }
                }

                return [
                    'id'            => $collegeTrainingPlanModel->id,
                    'name'          => $collegeTrainingPlanModel->name,
                    'type'          => $collegeTrainingPlanModel->type,
                    'campus'        => $collegeTrainingPlanModel->campus,
                    'planStartTime' => formatDateYmd($collegeTrainingPlanModel->planStartTime),
                    'planEndTime'   => formatDateYmd($collegeTrainingPlanModel->planEndTime),
                    'createdAt'     => $collegeTrainingPlanModel->createdAt->toDateTimeString(),
                    'status'        => $collegeTrainingPlanModel->status,
                    'planNum'       => $planNum,                                        //计划参训人数
                    'actualNum'     => (int)$actualNum,                                 //实际参训人数
                    'planRate'      => BaseService::formatPercent($actualNum, $planNum),//参训率
                    'totalUser'     => (int)$totalUser,                                 //考试人数
                    'okUser'        => (int)$okUser,                                    //合格人数
                    'okRate'        => BaseService::formatPercent($okUser, $totalUser), //合格率
                ];
            }
        );

        return [
            'lists' => $list,
            'count' => $paginator->total(),
            'pageSize' => $pageSize,
            'pageNum' => $pageNum,
            'pageCount' => ceil($paginator->total() / $paginator->perPage()),
        ];
    }

    /**
     * 添加培训计划
     * @param $request
     * @throws Exception
     */
    public static function addTrainingPlans($request)
    {
        try {
            $planStartTime = strtotime($request->planStartTime);
            $planEndTime = strtotime($request->planEndTime);
            self::getPlansCountByTime($request->campus,$planStartTime, $planEndTime);//查询当前时间段内是否已存在计划
            $courseStartTime = self::getCourseStartTime($planStartTime, $planEndTime);//理论考试开始时间 默认每周二下午14:00
            $data = [
                'name' => $request->name,
                'campus' => $request->campus,
                'type' => $request->type,
                'status' => CollegeTrainingPlanModel::TRAINING_PLANS_STATUS_DEFAULT,
                'planStartTime' => $planStartTime,
                'planEndTime' => $planEndTime,
                'courseStartTime' => $courseStartTime,
            ];
            CollegeTrainingPlanModel::addTrainingPlans($data);
        } catch (Exception $e) {
            handleException($e);
        }
    }

    /**
     * 获取单次培训计划 考试时间
     * @param $planEndTime
     * @param $planStartTime
     * @return false|int
     */
    public static function getCourseStartTime($planStartTime, $planEndTime)
    {
        $courseStartTime = 0;//理论考试开始时间 默认每周二下午14:00
        for ($i = 0; $i < ($planEndTime - $planStartTime) / 86400; $i++) {
            if (date('w', $planStartTime + $i * 86400) == 2) {
                $courseStartTime = strtotime(date('Y-m-d 14:00', $planStartTime + $i * 86400));
            }
            if ($courseStartTime > 0) {
                break;
            }
        }
        return $courseStartTime;
    }

    /**
     * 修改培训计划
     * @param $request
     * @throws Exception
     */
    public static function updateTrainingPlans($request)
    {
        try {
            $planStartTime = strtotime($request->planStartTime);
            $planEndTime = strtotime($request->planEndTime);
            self::getPlansCountByTime($request->campus,$planStartTime, $planEndTime,$request->id);//查询当前时间段内是否已存在计划
            $courseStartTime = self::getCourseStartTime($planStartTime, $planEndTime);//理论考试开始时间 默认每周二下午14:00
            $data = [
                'name' => $request->name,
                'campus' => $request->campus,
                'type' => $request->type,
                'planStartTime' => $planStartTime,
                'planEndTime' => $planEndTime,
                'courseStartTime' => $courseStartTime,
            ];
            CollegeTrainingPlanModel::setTrainingPlansInfoById($request->id, $data);
        } catch (Exception $e) {
            handleException($e);
        }
    }

    /**
     * get info
     * @param $request
     * @return array
     */
    public static function getTrainingPlansInfo($request)
    {
        $coursesInfo = CollegeTrainingPlanModel::getTrainingPlansInfoById($request->id);
        if ($coursesInfo) {
            $coursesInfo = $coursesInfo->toArray();
            $coursesInfo['planStartTime'] = formatDateYmd($coursesInfo['planStartTime']);
            $coursesInfo['planEndTime'] = formatDateYmd($coursesInfo['planEndTime']);
            $coursesInfo['courseStartTime'] = date('Y-m-d H:i', $coursesInfo['courseStartTime']);
            $coursesInfo['createdAt'] = formatDate(strtotime($coursesInfo['createdAt']));
        }
        return $coursesInfo;
    }


    /**
     * 关闭培训计划
     * @param $request
     * @return mixed|void
     */
    public static function deleteTrainingPlans($request)
    {
        CollegeTrainingPlanModel::setTrainingPlansInfoById($request->id, [
            'status' => CollegeTrainingPlanModel::TRAINING_PLANS_STATUS_OFF
        ]);

    }

    /**
     *批量添加培训计划
     * @param $request
     */
    public static function addBatchTrainingPlans($request)
    {
        $campus    = $request->campus;//校区
        $count     = $request->count; //本期培训期数（在培训计划名称后面自动加上培训期数，下一个计划名称累加期数）
        $years     = $request->years; //年份
        $batchData = [];
        if ($years == date('Y')) {//本年度
            $startTime = strtotime(date('Y-m-d'));
            $endTime   = strtotime(date('Y-12-31'));
        } else {
            $startTime = strtotime(date($years . '-1-1'));
            $endTime   = strtotime(date($years . '-12-31'));
        }
        $baseStartTime = $startTime;
        $time          = time();
        $baseData      = [
            'createdAt'    => $time,
            'updatedAt'    => $time,
            'createdByUid' => $request->userInfo->id,
            'type'         => CollegeTrainingPlanModel::TYPE_CAMPUS,
            'status'       => CollegeTrainingPlanModel::TRAINING_PLANS_STATUS_DEFAULT,
        ];
        $weekCount     = ceil(($endTime - $startTime) / 86400 / 7);//周数 培训周期，默认从周一到周日 且必须从周一开始
        foreach ($campus as $v) {       //循环校区
            $startTime = $baseStartTime;//每个校区初始化时间都一样
            for ($i = 0; $i < $weekCount; $i++) {//循环期数
                $name            = CollegeTrainingPlanModel::TRAINING_PLANS_CAMPUS_MAPPING[$v] . '-第' . ($count + $i) . '期';
                $courseStartTime = self::getCourseStartTime($startTime, $endTime);//理论考试开始时间 默认每周二下午14:00
                //培训周期 周一到周五
                if (date('w', $startTime) == 1) {//判断是否为周一
                    $planStartTime = $startTime;
                } else {
                    $planStartTime = strtotime(date('Y-m-d', $courseStartTime - 86400));
                }
                if ($planStartTime < $startTime) {              //周一不在当前时间内，则从下周开始
                    $planStartTime = $planStartTime + 7 * 86400;//下周一
                }
                if ($planStartTime > $endTime) {//本期开始时间大于本年结束时间则结束循环
                    break;
                }
                $planEndTime = $planStartTime + 6 * 86400;//本期周日
                $startTime   = $planStartTime + 7 * 86400;//下期开始时间
                $batchData[] = array_merge(
                    [
                        'name'            => $name,
                        'campus'          => $v,
                        'planStartTime'   => $planStartTime,
                        'planEndTime'     => $planEndTime,
                        'courseStartTime' => $courseStartTime,
                    ], $baseData
                );
            }
        }

        CollegeTrainingPlanModel::query()->insert($batchData);
    }

    /**
     * 查询当前时间段内是否已存在计划
     * @param $campus
     * @param $planStartTime
     * @param $planEndTime
     * @param $id
     * @return mixed|void
     */
    public static function getPlansCountByTime($campus, $planStartTime, $planEndTime, $id = 0)
    {
        if ($campus == CollegeTrainingPlanModel::TRAINING_PLANS_CAMPUS_OTHER) {
            return;
        }

        $count = CollegeTrainingPlanModel::query()
            ->whereIn('status', [CollegeTrainingPlanModel::TRAINING_PLANS_STATUS_DEFAULT, CollegeTrainingPlanModel::TRAINING_PLANS_STATUS_SUC])
            ->where('campus', $campus)
            ->when(
                $id, function ($query) use ($id) {
                $query->whereKeyNot($id);
            }
            )
            ->whereBetween('planStartTime', [$planStartTime, $planEndTime])
            ->count();
        if ($count > 0) {
            return BaseService::throwErr("当前时间段已存在培训计划");
        }
    }

}
